package com.wb3.meta.common.utils;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;

/**
 * @description 随机数工具类
 * @version 1.0
 */

public class RandomUtil {

	/**
	 * 
	 * @param n range
	 * @description 生成 [0-n)个不重复的随机数  
	 * @version 1.0
	 */
	public static List<Integer> getRandomList(int n, int range) {
        List<Integer> list = new ArrayList<Integer>();
        Random rand = new Random();
        boolean[] bool = new boolean[n];
        int num =0;
        for (int i = 0; i < n; i++) {
        	do {
        		int randInt = rand.nextInt(n);
                num = randInt - (randInt / range) * range;
            }while(bool[num]);
            bool[num] =true;
            list.add(num);
        }
        return list;
	}
	/** 
	 * 随机指定范围内N个不重复的数 
	 * 最简单最基本的方法 
	 * @param min 指定范围最小值 
	 * @param max 指定范围最大值 
	 * @param n 随机数个数 
	 */  
	public static List<Integer> randomCommon(int min, int max, int n){
		if (n > (max - min + 1) || max < min)
		{
			return null;
		}
		List<Integer> resultList = new ArrayList<>();
		int len = max-min+1;  
	      
	    if(max < min || n > len){  
	        return null;  
	    }  
	      
	    //初始化给定范围的待选数组
	    int[] source = new int[len];  
	       for (int i = min; i < min+len; i++){  
	        source[i-min] = i;  
	       }  
	         
	       int[] result = new int[n];  
	       Random rd = new Random();  
	       int index = 0;  
	       for (int i = 0; i < result.length; i++) {  
	        //待选数组0到(len-2)随机一个下标
	           index = Math.abs(rd.nextInt() % len--);  
	           //将随机到的数放入结果集
	           result[i] = source[index];  
	           //将待选数组中被随机到的数，用待选数组(len-1)下标对应的数替换
	           source[index] = source[len];  
	       }
	       for(int i = 0;i<= result.length-1;i++){
	    	   resultList.add(result[i]);
	       }
		return resultList;
	}  

	/**
	 * 
	 * @param n range
	 * @description 生成 [0-n)个不重复的随机数  
	 * @version 1.0
	 */
	public static List<Integer> getRandomList(int n) {
        List<Integer> list = new ArrayList<Integer>();
        Random rand = new Random();
        boolean[] bool = new boolean[n];
        int num = 0;
        for (int i = 0; i < n; i++) {
        	do {
                num = Math.abs(rand.nextInt(n)); //如果产生的数相同继续循环
            }while(bool[num]);
            bool[num] =true;
            list.add(num);
        }
        return list;
	}

	/**
	 * 
	 * @param n range
	 * @description 生成 一个[0-n)之间的一个随机数
	 * @version 1.0
	 */
	public static int getRandom(int n) {
		if(n == 0) {
			return 0;
		}
        Random rand = new Random();
        int randInt = rand.nextInt(n);
        //int num = randInt - (randInt / n) * n;
        return randInt;
	}

	/**
	 *
	 * @param min 指定范围最小值
	 * @param max 指定范围最大值
	 * @description 生成 一个[a,b]之间的一个随机数! 注意：要求，a，b都>=0
	 * @version 1.0
	 */
	public static int getRandom(int min, int max) {
		if( min < 0 || max < 0) {
			return -1;
		}
		if( min == max ){
			return min;
		}
		if(min > max){//swap
			int t = min;
			min = max;
			max = t;
		}
		int num = getRandom( max - min + 1);
		return ( min + num );
	}


	/**
	 * 从权重列表中随机一个元素
	 * @param weightList 权重列表
	 * @param <T> 元素的权重值，需要继承自{@linkplain Number}
	 * @return 返回随机元素的索引
	 */
	public static <T extends Number> int getRandomIndexByWeight(List<T> weightList)
	{
		final double weightSum = weightList.stream().mapToDouble(value -> value.doubleValue()).sum();
		final double weightRandom = Math.random() * weightSum;

		double weight = 0;
		for (int i = 0; i < weightList.size(); i++) {
			weight += weightList.get(i).doubleValue();

			if (weightRandom < weight)
				return i;
		}

		return 0;
	}
}
